<template>
  <el-form
    ref="fromRef"
    :model="formData"
    :label-width="labelWidth"
    :label-position="labelPosition"
    :size="size"
    :class="{ 'label-block': labelPosition === 'top' }"
  >
    <el-row :gutter="tableGutter">
      <template v-for="item in form_item">
        <el-col
          v-if="!hiddenItem[item.prop]"
          :key="item.prop"
          :span="item.col || col"
        >
          <el-form-item
            :label="item.label"
            :prop="item.prop"
            :rules="item.rules"
            :label-width="item.labelWidth"
            @click="onClickFormItem(item, $event)"
          >
            <slot
              v-if="item.type === 'slot'"
              :name="item.slotName"
              :data="formData[item.prop]"
              :column="item"
            ></slot>
            <component
              v-else
              v-model:value="formData[item.prop]"
              :disabled="disabled[item.prop]"
              :is="modules[`com-${item.type}`]"
              :column="item"
            />
          </el-form-item>
        </el-col>
      </template>
    </el-row>
    <el-form-item>
      <el-row class="btn-wrap" :class="[btnAlign]">
        <el-button
          v-for="item in button"
          :loading="item.loading"
          :key="item.key"
          :type="item.type"
          @click="handlerButton(item)"
        >
          {{ item.label }}
        </el-button>
      </el-row>
    </el-form-item>
  </el-form>
</template>
<script setup lang="ts">
import { useTableAttr } from '@/composables/table'
import createRules from './createRules.ts'
import { onMounted, ref, watch } from 'vue'
import { FormInstance } from 'element-plus'
import { FormButtonType, FormItemType, FormPropsType } from './type'

// 自动化的规则，通type属性，自动读到目录组件
const { modules } = useTableAttr()

// eslint-disable-next-line vue/valid-define-props
const props = withDefaults(defineProps<FormPropsType>(), {
  size: 'default',
  disabled: {},
  hiddenItem: {},
})

const handlerButton = async (data: FormButtonType) => {
  try {
    if (data.key === 'submit') await submit(data)
    if (data.key === 'cancel') await cancel(data)
    if (
      data.callback &&
      Object.prototype.toString.call(data.callback) === '[object Function]'
    ) {
      data.callback()
    }
  } catch (err) {
    console.log(err)
  }
}
const fromRef = ref<FormInstance>()
const submit = (data?: FormButtonType) => {
  return new Promise((resolve, reject) => {
    fromRef.value!.validate((valid: boolean) => {
      if (valid) {
        if (typeof props.beforeSubmit === 'function') {
          data!.loading = true
          props
            .beforeSubmit()
            .then((response) => {
              data!.loading = false
              resolve(true)
            })
            .catch(() => {
              data!.loading = false
            })
          return
        }
        resolve(true)
      } else {
        reject()
      }
    })
  })
}

const emit = defineEmits<{
  (e: 'onClickFormItem', val: FormItemType, el: PointerEvent)
}>()
const onClickFormItem = (event, el: PointerEvent) => {
  emit('onClickFormItem', event, el)
}

const resetField = () => {
  fromRef.value!.resetFields()
}
const cancel = (data) => {
  resetField()
}

const tableGutter = ref('')
const tableSize = ref('')
const form_item = ref<FormItemType[]>([])
watch(
  [() => props.gutter, () => props.size, () => props.formItem],
  (val) => {
    tableGutter.value = val[0]
    tableSize.value = val[1]
    form_item.value = createRules(val[2], props.formData)
  },
  { immediate: true },
)

defineExpose({ submit })
</script>

<style lang="scss" scoped>
:deep(.label-block) {
  .el-form-item__label {
    display: flex;
  }
}

.label-html {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: space-between;
}

.btn-wrap {
  display: flex;
  width: 100%;

  &.center {
    justify-content: center;
  }

  &.right {
    justify-content: flex-end;
  }
}
</style>
